package jeconbond.experiment.natural.prodpossibfrontier.generate;

import jeconbond.automata.INode;
import jeconbond.automata.IOutcome;
import jeconbond.automata.Node;
import jeconbond.automata.Outcome;
import jeconbond.experiment.generate.IAutomataGenerator;
import jeconbond.economic.resources.ResourceBasket;
import jeconbond.experiment.natural.prodpossibfrontier.process.IConneryExperimentContext;
import jeconbond.experiment.natural.prodpossibfrontier.ConneryExperimentSettings;
import jeconbond.Q.computation.IProgressFunc;
import jeconbond.Q.computation.ProdPossProgressFunc;
import jeconbond.experiment.process.IJEBExperimentContext;
import laboratoryQ.computation.IRandom;
import laboratoryQ.BaseUtils;

public class StaticProdPPFGraphGenerator implements IAutomataGenerator {
	static { System.out.println("remove just now IPPFGraphGenerator"); }

	public StaticProdPPFGraphGenerator() {
	}

	@Override
	public INode[] generate(IJEBExperimentContext iexperimentContext) {
		IConneryExperimentContext experimentContext = 
			(IConneryExperimentContext) iexperimentContext;
		ConneryExperimentSettings settings = experimentContext.getExperimentSettings();
		int n = settings.agentsCount;
		INode[] roots = new INode[n];
		double[] tmp = new double[2];
		IProgressFunc progressFunc = new ProdPossProgressFunc(
				settings.tankMul,
				settings.traktorMul
		); 
		for (int i = 0; i < n; i++) {
			roots[i] = generateOne(
					i, n, tmp, 
					experimentContext,
					progressFunc 
					);
		}
		return roots;
	}

	private static INode generateOne(
			int i, int count, double[] tmp,
			IConneryExperimentContext experimentContext,
			IProgressFunc progressFunc
	) {
		progressFunc.compute(i / (double)count, tmp);
		double tankPart = tmp[0];
		double traktorPart = tmp[1];
		ConneryExperimentSettings settings = experimentContext.getExperimentSettings();
		tankPart = reduce(tankPart, experimentContext.getRandom(), settings.fluctuationPart);
		traktorPart = reduce(traktorPart, experimentContext.getRandom(), settings.fluctuationPart);

		INode n1 = new Node("T&T:" + i + "n1");
		INode n2 = new Node("T&T:" + i + "n2");
		IOutcome n1TOn2 = new Outcome(n2, new ResourceBasket(settings.ironResource, 1.0));
		n1TOn2.setProducedResources(new ResourceBasket(settings.tankResource, tankPart));
		n1.getOutcomes().add(n1TOn2);
		IOutcome n2TOn1 = new Outcome(n1, new ResourceBasket(settings.ironResource, 1.0));
		n2TOn1.setProducedResources(new ResourceBasket(settings.traktorResource, traktorPart));
		n2.getOutcomes().add(n2TOn1);
		return n1;
	}

	private static double reduce(double val, IRandom r, double fluctuationPart) {
		val += BaseUtils.randomFromDist(r, -val, val) * fluctuationPart;
		return val;
	}
}
